package com.selen.component;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.json.JSONUtil;
import com.selen.dto.RequestLogDTO;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author Selen
 */
@Aspect
@Slf4j
@Component
public class ControllerAspect {

    @Around("execution(public * com.selen.controller.*.*(..))")
    @SneakyThrows
    public Object aroundAdvice(ProceedingJoinPoint pjp) {
        // 获取请求对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();
        // 构建控制器日志DTO实体: 包含本次请求的日志信息
        RequestLogDTO requestLogDTO = new RequestLogDTO();
        // 请求时间
        requestLogDTO.setRequestTime(DateUtil.now());
        // 开启计时器
        TimeInterval timer = DateUtil.timer(true);
        // 执行控制方法
        Object result = pjp.proceed(pjp.getArgs());
        // 停止计时器，获得总耗时
        requestLogDTO.setSpendTime(timer.intervalPretty());
        // 设置请求URL，请求方式，请求地址，类名，方法名，参数，响应数据等
        requestLogDTO.setUrl(request.getRequestURL().toString());
        requestLogDTO.setRequestMethod(request.getMethod());
        requestLogDTO.setRemoteAddress(request.getRemoteAddr());
        requestLogDTO.setClassName(pjp.getSignature().getDeclaringTypeName());
        requestLogDTO.setMethodName(pjp.getSignature().getName());
        requestLogDTO.setParameters(JSONUtil.toJsonStr(pjp.getArgs()));
        requestLogDTO.setResponseData(result);
        log.info("请求日志: " + requestLogDTO);
        return result;
    }
}
